home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of MacTutor - S…e Code for Volumes 1 to 5
/
The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin
/
Source Code
/
#39 (Dec 88)
/
SmoothSource
/
Smooth.asm
next >
Wrap
Assembly Source File
|
1988-06-23
|
31KB
|
1,234 lines
; ----------------------------------------------------------
; - Smoother: picCommenting polygons & non solo ------------
; - Raul Tabasso - via delle Isole 23/A - 00198 ROMA -------
; ------------------------------------------------------------------------
; WARNING: because this program is intended as a demo, there are some
; circumstances where a stronger error checking should be applied.
; Due to this, situations where a potential problem may arice,
; are marked with a (¿) symbol and a short advice is given.
; ------------------------------------------------------------------------
Include picCommenting:SmoothSource:Traps.D
; ----------------------------------------------
MBarHeight EQU $BAA ;GENERAL EQUATES
DoubleTime EQU $2F0
screenBits EQU $FF86
PortRect EQU 16
; ----------------------------------
PrGlue EQU $A8FD ;New print manager call
PrOpen EQU $C8000000 ;PrGlue's routine selectors
PrClose EQU $D0000000
PrintDefault EQU $20040480
PrStlDialog EQU $2A040484
PrJobDialog EQU $32040488
PrOpenDoc EQU $04000C00
PrCloseDoc EQU $08000484
PrOpenPage EQU $10000808
PrClosePage EQU $1800040C
PrPicFile EQU $60051480
PrError EQU $BA000000
; ----------------------------------
iCopies EQU 4 ;Print Manager Stuff
prInfo EQU 2
prJob EQU 62
rPage EQU 6
bJDocLoop EQU 6
; -----------------------------------
PicDwgBeg EQU 130 ;PicComment Kinds
PicDwgEnd EQU 131
PolyBegin EQU 160
PolyEnd EQU 161
PolyIgnore EQU 163
PolySmooth EQU 164
PicPlyClo EQU 165
SetLineWidth EQU 182
; ----------------------------------
Frame EQU 1 ;PolyVerbs
Fill EQU 2
Close EQU 4
; =======================================
; ------------ M A C R O --------------
; ---------------------------------------
MACRO prExec RoutineSelect =
MOVE.L #{RoutineSelect},-(SP) ;routine selector on stack
DC.W PrGlue ;execute trap
|
; ---------------------------------------
MACRO ShortComment Kind =
MOVE.W #{Kind},-(SP)
CLR.W -(SP)
CLR.L -(SP)
_PicComment
|
; ---------------------------------------
MACRO LongComment Kind,Size,Hand =
MOVE.W #{Kind},-(SP)
MOVE.W #{Size},-(SP)
MOVE.L {Hand},-(SP)
_PicComment
|
; ---------------------------------------
MACRO CheckItm MHandle,Item =
MOVE.L {MHandle}(A5),-(SP)
MOVE.W {Item},-(SP)
ST -(SP) ;check
_CheckItem
|
; ---------------------------------------
MACRO UnChkItm MHandle,Item =
MOVE.L {MHandle}(A5),-(SP)
MOVE.W {Item},-(SP)
CLR -(SP) ;uncheck
_CheckItem
|
; =======================================
; --------- Register usage --------------
PolyHand EQU A4
; -------------------------------------
BSR InitGlobals ;Do not rearrange the order of these subs
BSR InitMac
BSR GetHandles
BSR SetMenus
BSR SetWindow
BRA NewPoly ;init one
; ======================================
Loop _SystemTask
CLR.W -(SP)
MOVE.W #$FFFF,-(SP) ;Every event
PEA EVENTRECORD(A5)
_GetNextEvent
MOVE.B (SP)+,D0
BNE.S DoEvent
TST.W whileDrawing(A5) ;Check if we have to…
BNE.S TrackLine ;Idle line
BRA.S Loop
DoEvent MOVE.W WHAT(A5),D0
CMP.W #1,D0 ;is mousedown ?
BEQ MouseDown
CMP.W #3,D0 ;is keydown ?
BEQ KeyDown
CMP.W #6,D0 ;is update ?
BEQ UpDate
CMP.W #8,D0 ;is activate ?
BEQ DoAct
BRA.S Loop ;we don't support other events
; ==========================================
TrackLine
PEA CurPoint(A5)
_GetMouse
MOVE.L CurPoint(A5),D0
CMP.L OldPoint(A5),D0 ;Did we move since last time ?
BEQ.S Loop
;we are in XOR mode
MOVE.L LastPoint(A5),-(SP) ;start Pt
_MoveTo
MOVE.L OldPoint(A5),-(SP) ;overwrite old line
_LineTo
MOVE.L LastPoint(A5),-(SP) ;draw new line
_MoveTo
MOVE.L CurPoint(A5),-(SP)
_LineTo
MOVE.L CurPoint(A5),OldPoint(A5) ;c'est la vie
BRA.S Loop
; ------------------------------------------
DoAct MOVE.W MODIFY(A5),D0
BTST #0,D0 ;Activate or deactivate
BEQ.S DeAct
MOVE.L MESSAGE(A5),-(SP)
_SetPort
BSR DimMenu ;we only support copy menu
BSR PutGrow
BRA LOOP
DeAct BSR ActMenu ;Allow complete edit menu for DA
PEA GrowBox(A5)
_EraseRect ;clean it and
BSR PutGrow ;draw inactive
BRA LOOP
; -----------------------------
UpDate
MOVE.L TheWind(A5),-(SP)
_BeginUpdate
TST.W PolyDrawn(A5)
BEQ.S @0 ;branch if no poly
BSR ReDraw ;show poly
BRA.S @1
@0 TST.W WhileDrawing(A5)
BEQ.S @1 ;Exit if we are not either drawing
BSR DrawPoly ;Redraw part already drawn
MOVE.L LastPoint(A5),-(SP) ;redraw idle line
_MoveTo
MOVE.L OldPoint(A5),-(SP)
_LineTo
@1 BSR PutGrow
MOVE.L TheWind(A5),-(SP)
_EndUpdate
BRA LOOP
; ------------------------------
MouseDown
CLR.W -(SP)
MOVE.L WHERE(A5),-(SP)
PEA WINDOW(A5)
_FindWindow
MOVE.W (SP)+,D0
MOVE.W D0,D3 ;needed for zoom box
ADD.W D0,D0
MOVE.W WTABLE(PC,D0.W),D0
JMP WTABLE(PC,D0.W)
WTABLE DC.W LOOP-WTABLE
DC.W DoMenu-WTABLE
DC.W SysEvnt-WTABLE
DC.W DoContent-WTABLE
DC.W DoDrag-WTABLE
DC.W DoGrow-WTABLE
DC.W Loop-WTABLE
DC.W DoZoom-WTABLE
DC.W DoZoom-WTABLE
; --------------------------------
KeyDown CLR.L -(SP)
MOVE.W MESSAGE+2(A5),-(SP)
_MenuKey
MOVE.L (SP)+,MENU(A5)
BRA.S ExMenu
; --------------------------------
DoMenu
CLR.L -(SP)
MOVE.L WHERE(A5),-(SP)
_MenuSelect
MOVE.L (SP)+,MENU(A5)
ExMenu CLR.W -(SP)
_HiliteMenu ;Hilite off
MOVE.W MENU(A5),D0
CMP.W #4,D0 ;is a submenu ?
BLE.S @0
SUB.W #'A'-4-1,D0 ;Allign Submenu item-60 (65-4-1)
@0 ADD.W D0,D0
MOVE.W MTABLE(PC,D0.W),D0
JMP MTABLE(PC,D0.W)
MTABLE DC.W LOOP-MTABLE ;Menus
DC.W DoMela-MTABLE
DC.W DoFile-MTABLE
DC.W DoEdit-MTABLE
DC.W DoDo-MTABLE
DC.W DoPensize-MTABLE ;submenus
DC.W DoPat-MTABLE
DC.W DoPenscale-MTABLE
; -----------------------------
DoContent
CLR.L -(SP)
_FrontWindow
MOVE.L (SP)+,D0
CMP.L WINDOW(A5),D0
BEQ.S @0 ;Already in front
MOVE.L WINDOW(A5),-(SP)
_SelectWindow
@0 BSR ChkDoubClick ;set DoubleClick(A5) accordingly
MOVE.L WHERE(A5),MousLoc(A5)
PEA MousLoc(A5)
_GlobalToLocal
TST.W PolyDrawn(A5) ;do we have a poly yet ?
BNE Loop ;yes, no action implemented
TST.W whileDrawing(A5) ;No, is it initialized yet ?
BNE AddPoint ;yes, one more line for the poly
BRA PolyInit ;No, start a new one
; ----------------------------------------
DoDrag MOVE.L WINDOW(A5),-(SP)
MOVE.L WHERE(A5),-(SP)
PEA WBounds(A5)
_DragWindow
BRA LOOP
; ---------------------------------------
DoGrow CLR.L -(SP)
MOVE.L WINDOW(A5),-(SP)
MOVE.L WHERE(A5),-(SP)
PEA WSize(A5)
_GrowWindow
MOVE.L (SP)+,D0
BEQ LOOP ;Laizy, if not grown
MOVE.L WINDOW(A5),-(SP)
MOVE.L D0,-(SP)
ST -(SP)
_SizeWindow
PEA GrowBox(A5)
_EraseRect ;Erase it and
PEA GrowBox(A5) ;put it in the update rgn
_InvalRect
ResetWnd BSR CalcGrow
BSR ClipWind
BSR PutGrow
BRA LOOP
; -------------------------------------
DoZoom CLR.W -(SP)
MOVE.L WINDOW(A5),-(SP)
MOVE.L WHERE(A5),-(SP)
MOVE.W D3,-(SP) ;PartCode in or out
_TrackBox
TST.W (SP)+
BEQ LOOP
MOVE.L WINDOW(A5),A0
PEA PortRect(A0)
_EraseRect
CLR.W -(SP)
MOVE.L WINDOW(A5),-(SP)
MOVE.W D3,-(SP) ;PartCode in or out
SF -(SP)
_ZoomWindow
BRA ResetWnd
; ----------------------------------------
SysEvnt PEA EVENTRECORD(A5) ;make system happy
MOVE.L WINDOW(A5),-(SP)
_SystemClick
BRA LOOP
; ----------------------------------------
PolyInit
MOVE.L MousLoc(A5),-(SP) ;Start poly
_Moveto
MOVE.W #10,-(SP) ;XOR mode while drawing poly
_PenMode
MOVE.L #$10001,-(SP)
_PenSize ;Pen 1,1
MOVE.W #1,NumPoints(A5) ;First point
MOVE.L (PolyHand),A0
MOVE.L MousLoc(A5),(A0) ;write it in the list
MOVE.W #4,BytesWritten(A5)
ST whileDrawing(A5) ;follow mouse movement with a line
MOVE.L MousLoc(A5),LastPoint(A5) ;init points
MOVE.L MousLoc(A5),OldPoint(A5)
BRA Loop
; -----------------------------------------
AddPoint
TST.W DoubleClick(A5) ;user wants to close the poly ?
BNE ClosePoly
MOVE.L LastPoint(A5),-(SP) ;clear last line
_MoveTo
MOVE.L OldPoint(A5),-(SP)
_LineTo
_PenNormal ;Reset pen
MOVE.L LastPoint(A5),-(SP) ;add new line
_MoveTo
MOVE.L MousLoc(A5),-(SP)
_LineTo
MOVE.W #10,-(SP) ;put back XOR mode
_PenMode
BSR DoAdd ;put new point into the list
CMP.W #32760,BytesWritten(A5) ;Do not write past block
BPL ClosePoly ;force to close in case
BRA Loop
; ------------------------------------------
; Pack 'MousLoc' into compressed poly data list :
; A negative word signals a short delta; a word as follows…
; / bit 15 always set / bits 14-8 = dy (-64,63) / bits 7-Ø = dx (-128,127)/
; A positive word signals a 4 bytes point (Y & X) as usual
; WARNING(¿): this scheme won't work if high bit of point is negative
; (if a Y becomes <Ø a point will be interpreted as a short offset)
; -------------------------------------------
DoAdd ADDQ.W #1,NumPoints(A5) ;one more point
MOVE.L (PolyHand),A0 ;Pointer in A0
ADDA.W BytesWritten(A5),A0 ;get to mark
MOVE.W MousLoc(A5),D0 ;current Y
SUB.W LastPoint(A5),D0 ;D0 = Delta Y
CMP.W #63,D0 ;Dy must be in the range
BGT.S LongPoint ;doesn't fit
CMP.W #-64,D0
BMI.S LongPoint
;Y fits, now check X
MOVE.W MousLoc+2(A5),D1 ;current X
SUB.W LastPoint+2(A5),D1 ;D1 = Delta X
CMP.W #127,D1 ;Dy in a signed byte range ?
BGT.S LongPoint
CMP.W #-128,D1
BMI.S LongPoint
WordPoint ;Word format Point (compressed)
ADD.W #2,BytesWritten(A5) ;only 2 bytes for a short offset
BSET #7,D0 ;force a negative word to signal
MOVE.B D0,(A0)+ ;write Y offset
MOVE.B D1,(A0) ;write X offset
BRA.S AddDone
LongPoint ;Long format (normal)
ADD.W #4,BytesWritten(A5) ;not an offset, a Point
MOVE.L MousLoc(A5),(A0) ;always positive in our plane
AddDone
MOVE.L MousLoc(A5),LastPoint(A5) ;update
MOVE.L MousLoc(A5),OldPoint(A5)
RTS
; ------------------------
ClosePoly
ST PolyDrawn(A5) ;Poly is now completed
CLR.W whileDrawing(A5) ;we are through
_PenNormal ;reset mode and size
MOVE.L DoHand(A5),-(SP)
MOVE.W #1,-(SP)
_EnableItem ;allow unsmooth/smooth
MOVE.L FileHand(A5),-(SP)
MOVE.W #3,-(SP)
_EnableItem ;and print
MOVE.L (PolyHand),A0 ;Pointer in A0
MOVE.L (A0),MousLoc(A5) ;save extra code simulating a click
BSR DoAdd ;at last point (MousLoc) = first
_OpenRgn ;WARNING :(¿) should make sure our poly is not
BSR DrawPoly ;too big to fit in a region.
MOVE.L RgnHand(A5),-(SP) ;if it doesn't fit, we are dead
_CloseRgn
BSR SetPen
BSR CleanWind
BSR ReDraw ;show poly
BRA Loop
; =============================
DoMela
CMPI.W #2,MENU+2(A5)
BGT @1
;Show about dialog
CLR.L -(SP) ;space for result
MOVE.W #256,-(SP) ;ID
CLR.L -(SP) ;NIL storage
MOVE.L #-1,-(SP) ;in front
_GetNewDialog
MOVE.L (SP)+,A2
@0 CLR.L -(SP)
PEA ItmHit(A5)
_ModalDialog
CMP.W #1,ITMHIT(A5)
BNE.S @0
MOVE.L A2,-(SP)
_DisposDialog
BRA LOOP
@1 MOVE.L MelaHand(A5),-(SP) ;Get DA
MOVE.W MENU+2(A5),-(SP)
PEA DskName(A5)
_GetItem
CLR.W -(SP)
PEA DskName(A5)
_OpenDeskAcc
MOVE.W (SP)+,D0
BRA Loop
; ---------------------------------
DoFile
MOVE.W MENU+2(A5),D0 ;Item Num
ADD.W D0,D0
MOVE.W M1TAB(PC,D0.W),D0
JMP M1TAB(PC,D0.W)
M1TAB DC.W LOOP-M1TAB
DC.W NewPoly-M1TAB
DC.W PageSetup-M1TAB
DC.W Print-M1TAB
DC.W LOOP-M1TAB ;Laser Pen Menu
DC.W Quit-M1TAB
;-----------------------------------
DoEdit
CLR.L -(SP) ;Check if DA in front
_FrontWindow
MOVE.L (SP)+,A0
CMP.L TheWind(A5),A0
BEQ DoScrap ;branch if our wind in front
CLR.B -(SP) ;System Wind Frontmost
MOVE.W MENU+2(A5),-(SP)
SUBQ.W #1,(SP) ;balance different numbering
_SysEdit
TST.B (SP)+ ;get rid of bool
BRA LOOP
;------------------------------
NewPoly
CLR.W PolyDrawn(A5) ;clear poly
CLR.W WhileDrawing(A5)
CLR.W NumPoints(A5)
CLR.W Liscio(A5) ;no poly, no smooth
MOVE.L DoHand(A5),-(SP) ;Menu Handle
MOVE.W #1,-(SP)
PEA 'Smooth'
_SetItem ;reset
MOVE.L DoHand(A5),-(SP)
MOVE.W #1,-(SP)
_DisableItem ;no smooth menu and
MOVE.L FileHand(A5),-(SP) ;no print active
MOVE.W #3,-(SP)
_DisableItem
BSR CleanWind
BRA Loop
;------------------------------
PageSetup
prExec PrOpen ;open the driver
BSR CheckErr ;driver ok
CLR.W -(SP) ;Style Dialog
MOVE.L PrintRec(A5),-(SP)
prExec PrStlDialog
MOVE.W (SP)+,D0 ;forget it
prExec PrClose
BRA Loop
; =========================================
Print
MOVE.L D3,-(SP) ;save D3
PEA SavePort(A5) ;Save current port
_GetPort
prExec PrOpen ;open the driver
BSR CheckErr ;driver opened successfully ?
CLR.W -(SP) ;Job Dialog
MOVE.L PrintRec(A5),-(SP)
prExec PrJobDialog
MOVE.W (SP)+,D0
BEQ PrintDon ;canceled?
BSR OroCurs ;put watch curs
CLR.L -(SP) ;Open Print Port
MOVE.L PrintRec(A5),-(SP)
CLR.L -(SP)
CLR.L -(SP)
prExec PrOpenDoc
MOVE.L (SP)+,PrintPort(A5)
BSR CheckErr ;problems?
MOVE.L PrintRec(A5),A0 ;Initialize New Graph Port
MOVE.L (A0),A0
PEA prInfo+rpage(A0)
_ClipRect
MOVEQ #1,D3 ;assume Spool
MOVE.L PrintRec(A5),A0
MOVE.L (A0),A0
TST.B prJob+bjDocLoop(A0) ;Check if Draft or Spool
BNE.S @1
MOVE.W prJob+iCopies(A0),D3 ;Set Num copies if Draft
@1 SUBQ.W #1,D3 ;for DBRA
PageLoop
MOVE.L PrintPort(A5),-(SP) ;get ready to draw
CLR.L -(SP)
prExec PrOpenPage ;new page
BSR CheckErr ;are we ok?
MOVE.L CurPen(A5),-(SP) ;Set size and…
_PenSize
MOVE.L CommentHand(A5),A1 ;scaling
MOVE.L (A1),A0 ;deference handle
MOVE.W #12,(A0)+ ;numerator = 72/6 and…
MOVE.W CurScale(A5),(A0) ;denominator in dpi/6
LongComment SetLineWidth,4,A1
BSR MakePoly ;do it
MOVE.L PrintPort(A5),-(SP)
prExec PrClosePage ;page done
BSR CheckErr
DBRA D3,PageLoop ;next page
MOVE.L PrintPort(A5),-(SP)
prExec PrCloseDoc ;document done
BSR CheckErr
MOVE.L PrintRec(A5),A0
MOVE.L (A0),A0
TST.B prJob+bjDocLoop(A0) ;Check if Draft or Spool
BEQ.S PrintDon ;Branch if draft
MOVE.L PrintRec(A5),-(SP) ;spool to printer
CLR.L -(SP)
CLR.L -(SP)
CLR.L -(SP)
PEA PrStatus(A5)
prExec PrPicFile ;print spool file
BSR CheckErr
PrintDon prExec PrClose ;close driver
MOVE.L SavePort(A5),-(SP)
_SetPort ;restore port
MOVE.L (SP)+,D3 ;register and
_InitCursor ;arrow curs
BRA Loop
; --------------------
CheckErr CLR.W -(SP) ;WARNING (¿)
prExec PrError ;if an error occurs we have no handler
MOVE.W (SP)+,D0 ;Err code in D0
BNE Error ;this just goes to the finder
RTS
; ===============================
Quit _ExitToShell ;ciao
; ===============================
DoScrap
TST.W PolyDrawn(A5)
BEQ Loop ;nothing to clip
PEA WRect(A5) ;(¿) Not a correct rect
_ClipRect ;it's here just to save code
CLR.L -(SP)
PEA WRect(A5) ;(¿) should use a better rect
_OpenPicture ;(¿) Do we have enough memory for a pict?
MOVE.L (SP)+,A2 ;PicHandle
ShortComment PicDwgBeg ;yes, it's the format you know
BSR MakePoly ;do it
ShortComment PicDwgEnd
_ClosePicture
BSR ClipWind ;restore clip
CLR.L -(SP)
_ZeroScrap
MOVE.L (SP)+,D0
BNE Error
MOVE.L A2,A0
_GetHandleSize ;how big is the pict
CLR.L -(SP)
MOVE.L D0,-(SP) ;lenght
MOVE.L #'PICT',-(SP) ;ResType
MOVE.L (A2),-(SP) ;Ptr Pict
_PutScrap ;put it down
MOVE.L (SP)+,D0
BNE Error
MOVE.L A2,-(SP)
_KillPicture ;Get rid of it
BRA Loop
; -------------------------------
DoDo ;Smooth or unsmoooth
MOVE.L DoHand(A5),-(SP) ;Menu Handle
MOVE.W #1,-(SP) ;item num
NOT.W Liscio(A5) ;set & check Smooth flag
BEQ.S @0 ;branch accordingly
LEA DrawSmooth(PC),A3 ;routine to call in A3
PEA 'Unsmooth' ;load proper name
BRA.S @1
@0 LEA DrawPoly(PC),A3 ;no smooth
PEA 'Smooth'
@1 _SetItem
_OpenRgn
JSR (A3) ;WARNING :(¿) should make sure our poly is not
MOVE.L RgnHand(A5),-(SP) ;too big to fit in a region
_CloseRgn ;if it doesn't fit, we are dead
BSR CleanWind
BSR ReDraw
BRA Loop
; ===============================
DoPensize
UnChkItm PenHand,CurPen(A5) ;uncheck old
MOVE.W MENU+2(A5),CurPen(A5) ;v
MOVE.W MENU+2(A5),CurPen+2(A5) ;h
CheckItm PenHand,CurPen(A5) ;check new
TST.W PolyDrawn(A5)
BEQ Loop
BSR SetPen
BSR CleanWind
BSR Redraw
BRA Loop
;------------------------------
DoPat
UnChkItm FpatHand,ChkPat(A5) ;uncheck old
MOVE.W MENU+2(A5),ChkPat(A5)
CheckItm FpatHand,ChkPat(A5) ;check new
MOVE.W MENU+2(A5),D0
SUBQ.W #1,D0
ADD.W D0,D0
MOVE.W PatTab(PC,D0.W),CurPat(A5) ;get offset constant to PAT
TST.W PolyDrawn(A5)
BEQ Loop
BSR CleanWind
BSR ReDraw
BRA Loop
PatTab DC.W -8 ;White
DC.W -32 ;LtGray
DC.W -24 ;Gray
DC.W -40 ;DkGray
DC.W -16 ;Black
; --------------------------------
DoPenscale
UnChkItm PscaleHand,Chkscale(A5) ;uncheck old
MOVE.W MENU+2(A5),Chkscale(A5)
CheckItm PscaleHand,Chkscale(A5) ;check new
MOVE.W MENU+2(A5),D0
SUBQ.W #1,D0
ADD.W D0,D0
MOVE.W SclTab(PC,D0.W),CurScale(A5) ;get scale factor
BRA Loop
SclTab ;unsign byte values (0-255)
DC.W 12 ; 72/6
DC.W 25 ; 150/6
DC.W 50 ; 300/6
DC.W 100 ; 600/6
DC.W 200 ;1200/6
; =================================
SetPen
TST.W WhileDrawing(A5) ;don't change pen if drawing poly
BNE.S @0
MOVE.L CurPen(A5),-(SP)
_PenSize
@0 RTS
; --------------------------------
Redraw ;no poly to work with
TST.W CurPat(A5) ;is our poly filled ?
BEQ.S @0 ;No fill if CurPat=Ø
BSR FillPoly
@0 TST.W Liscio(A5) ;is poly smoothed ?
BNE.S DrawSmooth
DrawPoly
MOVE.W NumPoints(A5),D4 ;Total num of points
SUBQ.W #2,D4 ;sub 1 for DBRA and 1 for _Moveto
BGT.S @0 ;check reasonable poly (>2 points)
RTS ;return if not to consider a poly
@0 MOVE.L PolyHand ,A0 ;No surprise
_HLock ;Line and LineTo can cause relocation
BNE Error
MOVE.L (PolyHand),A3 ;Pointer to Poly data
MOVE.L (A3)+,-(SP) ;first point
_MoveTo
NextLine
TST.W (A3) ;Check for bit 15 (sign)
BPL.S LongPt ;IF set do Long ELSE do Short
ShortPt MOVE.B (A3)+,D1 ;dY: a signed 7 bits offset
BTST #6,D1 ;Test sign bit:a negative offset ?
BNE.S @0 ;yes, flag bit can stay
BCLR #7,D1 ;else (if positive) clear it
@0 EXT.W D1 ;DY as a word
SWAP D1 ;in hi word D1 now
MOVE.B (A3)+,D1 ;signed byte dx
EXT.W D1 ;dx in low word
MOVE.L D1,-(SP) ;offset on stack
_Line ;draw to
BRA.S NxLn
LongPt MOVE.L (A3)+,-(SP)
_LineTo ;a point
NxLn DBRA D4,NextLine
MOVE.L PolyHand ,A0 ;free again
_HUnLock
BNE Error
RTS
; ---------------------------
DrawSmooth
BSR UnPackPoly ;we need normal points to work
MOVE.L PolyBuffer(A5),A0 ;our temporary poly
_HLock
BNE Error
MOVE.L PolyBuffer(A5),A0
;Emulating a High-Level call
MOVE.W NumPoints(A5),-(SP) ;First param
MOVE.L (A0),-(SP) ;second, a Ptr to points list
BSR SmoothPoly ;fortissimo
MOVE.L PolyBuffer(A5),A0
_HUnLock ;free again
BNE Error
RTS
; ===================================================================
; SmoothPoly (NumPt:INTEGER; PtrPolyList:PTR)
; (¿) Implementation good for poly side<1024 pixels of length
; The resulting smoothed polygon closely resembles the laser output
; -------------------------------------------------------------------
LineTo EQU $91 ;trap num
; ----------------------------------
; ---------- Stack Frame -----------
; ----------------------------------
NumPt EQU 12
PtrList EQU 8
ParamBytes EQU 6
;
A EQU -2
B EQU -4
Av EQU -6
Bv EQU -8
X EQU -10
Y EQU -12
Line EQU -16
OldW EQU -18
OldQ EQU -20
;
Locals EQU -20
; ====================================================
; The following is a Basic translation of the algorithm
; Comments in the Asm source refer to these integer variables
; Note that the two version slightly differs where necessary
; P(c,n) is a bidimensional array of points:
; P(0,n)=Y P(1,n)=X ; n=point index
; ----------------------------------------------------
; X1=P(1,1)-P(1,0):Y1=P(0,1)-P(0,0)
; X=X1\2+P(1,0):Y=Y1\2+P(0,0)
; MOVETO X,Y
; FOR j=1 TO NumPt
; X0=X1:Y0=Y1
; X1=P(1,j+1)-P(1,j):Y1=P(0,j+1)-P(0,j)
; T=(ABS(X1+X0)+ABS(Y1+Y0))\8
; IF T<2 THEN T=2
; Z=T*T*2:Du=T+1
; FOR n=0 TO T
; Du=Du-1:Q=n*n:w=Du*Du
; A=(Q*X1-w*X0)/Z+P(1,j)
; B=(Q*Y1-w*Y0)/Z+P(0,j)
; LINETO A,B
; NEXT
; NEXT
; LINETO X,Y
; ==================================
SmoothPoly ;If called from hi level think of it
LINK A6,#Locals ;like a ToolBox procedure
MOVEM.L A1-A4/D0-D7,-(SP) ;save the world
MOVE.L PtrList(A6),A4 ;A4 point list Ptr
MOVE.W #LineTo,D0 ;Trap num for LineTo
_GetTrapAddress ;save some cycle
MOVE.L A0,A3 ;store in A3 for later use
CLR.L Bv(A6) ;clear last drawn point
MOVE.L (A4),D4 ;First Pt
MOVE.L 4(A4),D5 ;second Pt
SUB.W D4,D5 ;X1
MOVE.W D5,D1 ;safe in D1
SWAP D4 ;push y in low word
SWAP D5
SUB.W D4,D5 ;Y1
MOVE.W D5,D0 ;safe in D0
ASR.W #1,D1 ;divs by 2 with no sign loss
ASR.W #1,D0
ADD.W D4,D0 ;D0=Y+(Y2-Y1)/2
ADD.W 2(A4),D1 ;D1=X+(X2-X1)/2
MOVE.W D0,Y(A6) ;First point recorded for closing
MOVE.W D1,X(A6)
MOVE.W D1,-(SP)
MOVE.W D0,-(SP)
_MoveTo
SUBQ.W #1,NumPt(A6) ;ready to start
NextPoint
MOVE.L D5,D4 ;Y0=Y1 : X0=X1
ADDQ.L #4,A4 ;Current=Next
MOVE.L 4(A4),D5 ;Next Point in D5
SUB.W 2(A4),D5 ;X1=NextX-CurX
MOVE.W D5,D6 ;safe in D6
SWAP D5 ;push Y down
SUB.W (A4),D5 ;Y1=NextY-CurY
MOVE.W D5,D0 ;safe in D0
; Calc num iteration now (T) ------------
ADD.W D4,D0 ;D0=Y0+Y1
BPL.S @1
NEG.W D0 ;ABS
@1 SWAP D4 ;x in low word
ADD.W D4,D6 ;D6=X0+X1
BPL.S @2
NEG.W D6 ;ABS
@2 SWAP D4 ;y back in low
ADD.W D0,D6 ;D6=(D0^2+D6^2)
LSR.W #3,D6 ;T=D6\8 (step)
CMP.W #2,D6 ;T=>2 at least
BPL.S @0
MOVEQ #2,D6 ;T=D6
@0 MOVE.W D6,D7
MULU D7,D7 ;T*T
LSL.W #1,D7 ;Z=D7 (T*T*2)
MOVEQ #0,D3 ;n=0
MOVE.W D6,D0 ;init values
ADDQ.W #1,D0
MULU D0,D0
MOVE.W D0,OldW(A6)
MOVE.W #1,OldQ(A6)
Curva
MOVE.W D6,D0 ;Calc W (T*T), avoiding slow MULU
ADD.W D0,D0
ADDQ.W #1,D0
SUB.W D0,OldW(A6) ;W=(OldW)-2T+1
MOVE.W OldW(A6),D0
MOVE.W D3,D1 ;Calc Q (n*n), avoiding slow MULU
ADD.W D1,D1
SUBQ.W #1,D1
ADD.W D1,OldQ(A6) ;Q=(OldQ)+2n-1
MOVE.W OldQ(A6),D1
ADDQ.W #1,D3 ;n=n+1
MOVE.W D0,D2 ;Calc B ------
MULS D4,D2 ;Y0*W
MOVE.L D2,A2
MOVE.W D1,D2
MULS D5,D2 ;Y1*Q
SUB.L A2,D2
DIVS D7,D2 ;/Z
ADD.W (A4),D2 ;+ CurPt Y
MOVE.W D2,B(A6) ;safe
SWAP D4 ;push Xs down
SWAP D5
MOVE.W D0,D2 ;Calc A ------
MULS D4,D2 ;X0*W
MOVE.L D2,A2
MOVE.W D1,D2
MULS D5,D2 ;X1*Q
SUB.L A2,D2
DIVS D7,D2 ;/Z
ADD.W 2(A4),D2 ;+ CurPt X
MOVE.W D2,A(A6) ;save
SWAP D4
SWAP D5
CMP.W Av(A6),D2 ;did we move? (over the unit)
BNE.S @0 ;much faster to check it here, than go
MOVE.W B(A6),D2 ;through the ROM with a useless Lineto
CMP.W Bv(A6),D2
BEQ.S @1
@0 MOVE.L B(A6),-(SP)
JSR (A3) ;LineTo
MOVE.L B(A6),Bv(A6)
@1 DBRA D6,Curva
SUBQ.W #1,NumPt(A6)
BGT NextPoint
Done MOVE.L Y(A6),-(SP) ;back to first point
JSR (A3) ;LineTo
MOVEM.L (SP)+,A1-A4/D0-D7 ;restore the world
UNLK A6
MOVE.L (SP)+,A0 ;RTS
ADDQ #ParamBytes,SP
JMP (A0) ;back home
; ---------------------------------
UnPackPoly
MOVE.L PolyBuffer(A5),A0 ;copy the poly here
MOVE.L (A0),A0 ;Ptr to temporary space
MOVE.W NumPoints(A5),D0
MOVE.W BytesWritten(A5),D1
MOVE.L (PolyHand),A1 ;Ptr to packed poly in A1
MOVE.L (A1)+,(A0)+ ;first point
SUBQ.W #1,D0 ;one pt processed
MOVE.L (A1),-4(A1,D1.W) ;add 2nd pt to the end of list
Spacca TST.W (A1) ;Check if short or long point
BMI.S @0
MOVE.L (A1)+,(A0)+ ;nothing to unpack
DBRA D0,Spacca
BRA.S SpacDon
@0 MOVE.L -4(A0),(A0) ;point to add the offset to
MOVE.B (A1)+,D1 ;dY: a signed 7 bits offset
BTST #6,D1 ;a negative offset ?
BNE.S @1 ;yes, flag bit can stay
BCLR #7,D1 ;positive: clear flag bit
@1 EXT.W D1 ;DY as a word
ADD.W D1,(A0)+
MOVE.B (A1)+,D1 ;signed byte dx
EXT.W D1 ;dx in low word
ADD.W D1,(A0)+
DBRA D0,Spacca
SpacDon RTS
; ========================================================
FillPoly
MOVE.L RgnHand(A5),-(SP) ;Our Handle
MOVE.W CurPat(A5),D0 ;Offset to pat
MOVE.L (A5),A0 ;Ptr to QD's Globals
PEA 0(A0,D0.W) ;fill it with Current Pat
_FillRgn
RTS
;-------------------------------
CleanWind
MOVE.L TheWind(A5),A0
PEA PortRect(A0)
_EraseRect
BSR PutGrow ;show it
RTS
; -------------------------------
ClipWind
MOVE.L TheWind(A5),A0
PEA PortRect(A0)
_ClipRect
RTS
; -------------------------------
PutGrow
MOVE.L #$10001,-(SP)
_PenSize ;Use pen 1,1 to draw
MOVE.L TempRgn(A5),-(SP) ;save
_GetClip
PEA GrowBox(A5) ;only the box
_ClipRect
MOVE.L TheWind(A5),-(SP)
_DrawGrowIcon
MOVE.L TempRgn(A5),-(SP) ;put back
_SetClip
BSR SetPen ;restore pen
RTS
; -------------------------------
CalcGrow
MOVE.L TheWind(A5),A0
LEA GrowBox(A5),A1 ;Recalculate new GrowBox
MOVE.L PortRect+4(A0),(A1) ;push bottom right point of window
SUB.W #15,(A1)+ ;make Top left box
SUB.W #15,(A1)+
MOVE.L PortRect+4(A0),(A1) ;and bottom right
RTS
; -------------------------------
ChkDoubClick ;Check if a double click
CLR.W DoubleClick(A5) ;assume not
MOVE.L WHEN(A5),D1 ;this click
SUB.L LastClick_T(A5),D1 ;ticks elapsed since last
CMP.L DoubleTime,D1 ;close enough togather?
BGT.S @0 ;branch if over 'DoubleTime'
MOVE.W WHERE(A5),D0 ;now check for position
SUB.W LastClick_W(A5),D0 ;delta Y
BPL.S @1 ;ABS
NEG.W D0
@1 MOVE.W WHERE+2(A5),D1 ;delta X
SUB.W LastClick_W+2(A5),D1
BPL.S @2 ;ABS
NEG.W D1
@2 ADD.W D0,D1 ;Dx+Dy
CMP.W #3,D1 ;allow for a 3 pix max distance
BGT.S @0
ST DoubleClick(A5) ;yes, it's a double click
@0 MOVE.L WHEN(A5),LastClick_T(A5) ;Record time and…
MOVE.L WHERE(A5),LastClick_W(A5) ;location
RTS
; ---------------------------------------
ActMenu BSR paramOnStack ;load the stack
_EnableItem ;3 items
_EnableItem ;to enable
_EnableItem
_DrawMenuBar
RTS
DimMenu BSR paramOnStack ;load the stack
_DisableItem ;3 items
_DisableItem ;to disable
_DisableItem
_DrawMenuBar
RTS
; ------
paramonStack
MOVE.L (SP)+,A0 ;RTS in A0
MOVE.L EditHand(A5),-(SP)
MOVE.W #1,-(SP) ;undo
MOVE.L EditHand(A5),-(SP)
MOVE.W #3,-(SP) ;cut
MOVE.L EditHand(A5),-(SP)
MOVE.W #5,-(SP) ;paste
JMP (A0)
; ==========================================
MakePoly
ShortComment PolyBegin ;Here starts our special Poly
ShortComment PicPlyClo ;always a closed Poly in our case
TST.W Liscio(A5) ;is our poly to be smoothed?
BEQ.S @1 ;branch if not
MOVE.L CommentHand(A5),A1 ;Handle to smooth verbs
MOVE.L (A1),A0 ;deference
MOVEQ #Frame+Close,D0 ;assume only closed and framed
TST.W CurPat(A5) ;is our poly filled ?
BEQ.S @0
ADDQ.W #Fill,D0 ;add fill verb
@0 MOVE.B D0,(A0) ;set verb = Close+Frame+(Fill)
LongComment PolySmooth,1,A1 ;smooth flag true
MOVE.L TempRgn(A5),-(SP) ;save clip
_GetClip
PEA ZeroRect(PC) ;if not aware of comments then no print
_ClipRect
BSR DrawPoly ;Pass laser original vertexes to be smoothed
MOVE.L TempRgn(A5),-(SP)
_SetClip ;allow others to print
ShortComment PolyIgnore ;ignore following poly if laser
@1 BSR ReDraw ;simulate spline for non-laser printers
ShortComment PolyEnd ;End special poly
RTS
;===========================================
InitGlobals
CLR.W CurPat(A5) ;No fill pat
MOVE.L #$10001,CurPen(A5) ;PenSize 1,1
MOVE.W #12,CurScale(A5) ;72 dpi
MOVE.W #1,ChkPat(A5) ;first pat checked
MOVE.W #1,Chkscale(A5) ;72 dpi checked
RTS
; ----------------------------------
InitMac
PEA -4(A5) ;Recite Mac pray
_InitGraf
_InitFonts
_InitWindows
_InitMenus
CLR.L -(SP) ; No restart procedure
_InitDialogs
_TEInit
_InitCursor
MOVE.L #$0000FFFF,D0 ; Flush all events
_FlushEvents
RTS
; -------------------------------------
SetWindow
MOVE.L (A5),A0 ;Pointer to QuickDraw Globals
LEA screenBits(A0),A0 ;Ptr to Bounds of Screen BitMap
MOVE.L 6(A0),WRect(A5) ;Get & set Screen Rect
MOVE.L 10(A0),WRect+4(A5)
PEA WRect(A5)
MOVE.L #$100010,-(SP) ;allow 16 Pixels inside
_InsetRect
MOVE.L WRect(A5),WBounds(A5) ;Init Draging bounds Rect
MOVE.L WRect+4(A5),WBounds+4(A5)
MOVE.L #$400080,WSize(A5) ;Grow Rect (64,128,768,768)
MOVE.L #$3000300,WSize+4(A5) ;(¿) should calc this rect
;according to PageSetUp
MOVE.W MBarHeight,D0 ;Center WRect on video
ADDI.W #18,D0 ;Title bar
ADD.W D0,WRect(A5) ;subtract Menu Height
CLR.L -(SP) ;Create our window
CLR.L -(SP)
PEA WRect(A5)
PEA 'Polygon' ;document:Polygon
MOVE.B #-1,-(SP)
MOVE.W #8,-(SP) ;has zoom box
MOVE.L #-1,-(SP)
CLR.B -(SP)
CLR.L -(SP)
_NewWindow
MOVE.L (SP),TheWind(A5) ;leave it on stack and save
_SetPort
BSR CalcGrow
BSR ClipWind
BSR PutGrow
RTS
;=================================
SetMenus
MOVEM.L A3/D3-D5,-(SP) ;save stuff
LEA MenuHndList(A5),A3 ;Stuff with MHandles from here on
MOVEQ #1,D3 ;Start with Menu 1
MOVEQ #4-1,D4 ;4 menus (-1 for DBRA)
MOVEQ #0,D5 ;before ID = 0
BSR PushMenus ;sequential ordering
MOVE.L MelaHand(A5),-(SP)
MOVE.L #'DRVR',-(SP)
_AddResMenu ;yes, we support DA
;add submenus
MOVEQ #'A',D3 ;Start with Menu 65
MOVEQ #2,D4 ;through menu 67
MOVEQ #-1,D5 ;hierarchical beforeID
BSR PushMenus
CheckItm PenHand,#1 ;check items
CheckItm FpatHand,#1
CheckItm PscaleHand,#1
_DrawMenuBar
MOVEM.L (SP)+,A3/D3-D5 ;restore stuff
RTS
; -------------------
PushMenus
CLR.L -(SP)
MOVE.W D3,-(SP) ;ID of Menu to get
_GetRMenu
MOVE.L (SP),(A3)+ ;Save Hndl trusting global ordering
MOVE.W D5,-(SP) ;Hndl was left on stack + beforeID
_InsertMenu
ADDQ.W #1,D3 ;Next ID
DBRA D4,PushMenus
RTS
; ---------------------------------------
GetHandles
MOVE.L #$7FFF,D0 ;ask for 32K
_NewHandle
BNE Error
MOVE.L A0,PolyHand
MOVE.L #$FFFE,D0 ;ask for 64K
_NewHandle
BNE Error
MOVE.L A0,PolyBuffer(A5)
MOVEQ #120,D0 ;Print Record Size
_NewHandle
MOVE.L A0,PrintRec(A5)
MOVE.L A0,-(SP)
prExec PrintDefault ;Fill it with defaults
MOVEQ #8,D0 ;enough for any comment data
_NewHandle
BNE Error
MOVE.L A0,CommentHand(A5)
CLR.L -(SP) ;our fill region
_NewRgn
MOVE.L (SP)+,RgnHand(A5)
CLR.L -(SP)
_NewRgn
MOVE.L (SP)+,TempRgn(A5) ;A dummy region
RTS
;========================================
ERROR BSR Bippa ;WARNING (¿)
BSR Bippa ;Best Error Handler routine ever written
BSR Bippa ;but I know you could do even better
_ExitToShell
; -----------------------------
Bippa MOVE.W #3,-(SP)
_SysBeep
RTS
; -----------------------------
OroCurs CLR.L -(SP) ;watch cursor
MOVE.W #4,-(SP)
_GetCursor
MOVE.L (SP)+,A0
MOVE.L (A0),-(SP)
_SetCursor
RTS
; ----------------------------------------------------
ZeroRect DC.W 0,0,0,0
; -----------------------------------------------------
; ------------------- GLOBALS -------------------------
; -----------------------------------------------------
WRect DS.B 8 ;Window stuff
GrowBox DS.B 8
WBounds DS.B 8
WSize DS.B 8
TheWind DS.L 1
WINDOW DS.L 1
MenuHndList DS.L 0 ;do not change this ordering!
MelaHand DS.L 1 ;Menu Handles
FileHand DS.L 1
EditHand DS.L 1
DoHand DS.L 1
PenHand DS.L 1 ;Hierarchical Menu Handles
FpatHand DS.L 1
PscaleHand DS.L 1
EVENTRECORD DS.B 0 ;My event.
WHAT DS.W 1
MESSAGE DS.L 1
WHEN DS.L 1
WHERE DS.L 1
MODIFY DS.W 1
MENU DS.L 1 ;Other…
PolyBuffer DS.L 1
PolyDrawn DS.W 1
whileDrawing DS.W 1
NumPoints DS.W 1
BytesWritten DS.W 1
LastPoint DS.L 1
CurPoint DS.L 1
OldPoint DS.L 1
MousLoc DS.L 1
LastClick_T DS.L 1
LastClick_W DS.L 1
DoubleClick DS.W 1
CurPat DS.W 1
CurPen DS.L 1
CurScale DS.W 1
ChkPat DS.W 1
Chkscale DS.W 1
Liscio DS.W 1
RgnHand DS.L 1
TempRgn DS.L 1
CommentHand DS.L 1
DskName DS.B 64
SavePort DS.L 1
PrintPort DS.L 1
PrintRec DS.L 1
PrStatus DS.B 26
ItmHit DS.W 1